﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml;

using Core;
using ClassLibrary;

namespace TestProject
{
    public partial class PhenotypeTableEdit : Form
    {
        private Model model;
        private PhenotypeTable phen_t;
        private CharacteristicDescription desc=null;
        private List<GenomePhenotypeLink> genome_links = new List<GenomePhenotypeLink>();
        private List<NaturalSelectionLink> natsel_links = new List<NaturalSelectionLink>();
        public PhenotypeTableEdit(Model m, PhenotypeTable table)
        {
            InitializeComponent();
            model = m;
            phen_t = table;
        }
        private void update()
        {
            charac_box.Items.Clear();
            name_box.Text = phen_t.name;
            phen_t = new PhenotypeTable(phen_t.path);
            foreach (CharacteristicDescription desc in phen_t.characteristic_table.Values)
            {
                charac_box.Items.Add(desc.name);
            }
        }
        private void PhenotypeTableEdit_Load(object sender, EventArgs e)
        {
            update();
            foreach (GenomePhenotypeLink link in model.model_genome_phenotype_links.Values)
            {
                if (link.path_to_phenotype_table == phen_t.path)
                    genome_links.Add(link);
            }
            foreach (NaturalSelectionLink link in model.model_natural_selection_links.Values)
            {
                if (link.path_to_phenotype_table == phen_t.path)
                    natsel_links.Add(link);
            }
        }

        private void charac_box_SelectedIndexChanged(object sender, EventArgs e)
        {
            foreach (CharacteristicDescription d in phen_t.characteristic_table.Values)
            {
                if ((string)charac_box.SelectedItem == d.name)
                {
                    desc = d;
                    break;
                }
            }
            degree_box.Value = desc.max_degree;
            degree_box.difference = 0;
        }

        private void add_butt_Click(object sender, EventArgs e)
        {
            NewCharac new_charac = new NewCharac(phen_t,genome_links,natsel_links,model.model_reproduction_links);
            if (new_charac.ShowDialog(this) == DialogResult.OK)
                update();
        }

        private void remove_butt_Click(object sender, EventArgs e)
        {
            MyXmlDocument doc = new MyXmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(phen_t.path));
            foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
            {
                if (node.Attributes[0].Value == desc.id.ToString())
                {
                    node.ParentNode.RemoveChild(node);
                    break;
                }
            }
            doc.Decrement(doc.DocumentElement.Attributes[1]);
            doc.Save(phen_t.path);
            foreach (GenomePhenotypeLink link in genome_links)
            {
                doc = new MyXmlDocument();
                doc.LoadXml(System.IO.File.ReadAllText(link.path));
                foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                {
                    if (node.Attributes[0].Value == desc.id.ToString())
                    {
                        node.ParentNode.RemoveChild(node);
                        break;
                    }
                }
                doc.Decrement(doc.DocumentElement.Attributes[4]);
                doc.Save(link.path);
            }
            foreach (NaturalSelectionLink link in natsel_links)
            {
                doc = new MyXmlDocument();
                doc.LoadXml(System.IO.File.ReadAllText(link.path));
                int id=0;
                string[] names =doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                doc.GetElementsByTagName("characteristic_names")[0].InnerText = null;
                for(int i=0;i<names.Count();i++)
                {
                    if (names[i]==desc.name)
                    {
                        id=i;
                        break;
                    }
                }
                List<string> namesl = names.ToList();
                namesl.RemoveAt(id);
                foreach (string s in namesl)
                {
                    doc.GetElementsByTagName("characteristic_names")[0].InnerText += s;
                    if (s != namesl.Last())
                        doc.GetElementsByTagName("characteristic_names")[0].InnerText += " ";
                }
                string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                List<string> max_val_l= max_val.ToList();
                max_val_l.RemoveAt(id);
                for(int i=0;i<max_val_l.Count();i++)
                {
                    doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val_l[i];
                    if (i!=max_val_l.Count()-1)
                        doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                }
                string[] inner1 = doc.GetElementsByTagName("characteristic_sets")[0].InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                string[] inner2 = doc.GetElementsByTagName("characteristic_sets")[1].InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                doc.GetElementsByTagName("characteristic_sets")[0].InnerText = null;
                doc.GetElementsByTagName("characteristic_sets")[1].InnerText = null;
                List<string> inner1_l = new List<string>();
                List<string> inner2_l = new List<string>();
                foreach (string s in inner1)
                {
                    List<string> l= s.Split(new char[] {' '},StringSplitOptions.RemoveEmptyEntries).ToList();
                    l.RemoveAt(id);
                    string ss=null;
                    for (int i = 0; i < l.Count(); i++)
                    {
                        ss += l[i];
                        if (i != l.Count() - 1)
                            ss += " ";
                    }
                    inner1_l.Add(ss);
                }
                foreach (string s in inner2)
                {
                    List<string> l = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    l.RemoveAt(id);
                    string ss = null;
                    for(int i=0;i<l.Count();i++)
                    {
                        ss += l[i];
                        if (i != l.Count()-1)
                            ss += " ";
                    }
                    inner2_l.Add(ss);                    
                }
                List<string> l1 =inner1_l.Distinct().ToList();
                List<string> l2 =inner2_l.Distinct().ToList();
                foreach (string s in l1)
                {
                    doc.GetElementsByTagName("characteristic_sets")[0].InnerText += " " + s + ";";
                }
                foreach (string s in l2)
                {
                    doc.GetElementsByTagName("characteristic_sets")[1].InnerText += " " + s + ";";
                }
                doc.Decrement(doc.DocumentElement.Attributes[3]);
                doc.Save(link.path);
            }
            foreach (ReproductionLink link in model.model_reproduction_links.Values)
            {
                if (link.path_to_phenotype_table == phen_t.path)
                {
                    doc = new MyXmlDocument();
                    doc.LoadXml(System.IO.File.ReadAllText(link.path));
                    int id = 0;
                    string[] names = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                    doc.GetElementsByTagName("characteristic_names")[0].InnerText = null;
                    for (int i = 0; i < names.Count(); i++)
                    {
                        if (names[i] == desc.name)
                        {
                            id = i;
                            break;
                        }
                    }
                    List<string> namesl = names.ToList();
                    namesl.RemoveAt(id);
                    foreach (string s in namesl)
                    {
                        doc.GetElementsByTagName("characteristic_names")[0].InnerText += s;
                        if (s != namesl.Last())
                            doc.GetElementsByTagName("characteristic_names")[0].InnerText += " ";
                    }
                    string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                    doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                    List<string> max_val_l = max_val.ToList();
                    max_val_l.RemoveAt(id);
                    for (int i = 0; i < max_val_l.Count(); i++)
                    {
                        doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val_l[i];
                        if (i != max_val_l.Count() - 1)
                            doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                    }
                    foreach (XmlNode node in doc.GetElementsByTagName("characteristic_sets"))
                    {
                        string[] inner1 = node.InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                        node.InnerText = null;
                        List<string> inner1_l = new List<string>();
                        foreach (string s in inner1)
                        {
                            List<string> l = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            l.RemoveAt(id);
                            string ss = null;
                            for (int i = 0; i < l.Count(); i++)
                            {
                                ss += l[i];
                                if (i != l.Count() - 1)
                                    ss += " ";
                            }
                            inner1_l.Add(ss);
                        }
                        List<string> l1 = inner1_l.Distinct().ToList();
                        foreach (string s in l1)
                        {
                           node.InnerText += " " + s + ";";
                        }
                    }
                    doc.Decrement(doc.DocumentElement.Attributes[3]);
                    doc.Save(link.path);
                }
            }
        }

        private void set_butt_Click(object sender, EventArgs e)
        {
            MyXmlDocument doc;
            if (degree_box.IsIncremented())
            {
                foreach (GenomePhenotypeLink link in genome_links)
                {
                    doc = new MyXmlDocument();
                    SetGenPhenLink value_set = new SetGenPhenLink(link, desc.id, desc.max_degree, degree_box.difference);
                    if (value_set.ShowDialog(this) != DialogResult.OK)
                    {
                        MessageBox.Show("Unable to increase degree without a link.\nPlease, create it.");
                        return;
                    }
                }
                for (int j = 0; j < degree_box.difference; j++)
                {
                    int degree = (int)degree_box.Value - j;
                    foreach (NaturalSelectionLink link in natsel_links)
                    {
                        doc = new MyXmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        int id = 0;
                        string[] names = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                        for (int i = 0; i < names.Count(); i++)
                        {
                            if (names[i] == desc.name)
                            {
                                id = i;
                                break;
                            }
                        }
                        string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                        max_val[id] = degree_box.Value.ToString();
                        doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                        for (int i = 0; i < max_val.Count(); i++)
                        {
                            doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val[i];
                            if (i != max_val.Count() - 1)
                                doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                        }
                        int[] values = new int[max_val.Count()];
                        for (int i = 0; i < max_val.Count(); i++)
                        {
                            values[i] = Convert.ToInt32(max_val[i]);
                        }
                        values[id] = 0;
                        List<List<int>> comb = new List<List<int>>(); ;
                        if (values.Count() > 1)
                        {
                            comb = Functions.combine(values);
                        }
                        else
                        {
                            comb.Add(new List<int>());
                            comb[0].Add(values[id]);
                        }
                        foreach (List<int> l in comb)
                        {
                            l[id] = degree;
                            foreach (int i in l)
                            {
                                doc.GetElementsByTagName("characteristic_sets")[0].InnerText += " " + i.ToString();
                            }
                            doc.GetElementsByTagName("characteristic_sets")[0].InnerText += ";";
                        }
                        doc.Save(link.path);
                    }
                    foreach (ReproductionLink link in model.model_reproduction_links.Values)
                    {
                        if (link.path_to_phenotype_table == phen_t.path)
                        {
                            doc = new MyXmlDocument();
                            doc.LoadXml(System.IO.File.ReadAllText(link.path));
                            foreach (XmlNode node in doc.GetElementsByTagName("characteristic_sets"))
                            {
                                if (node.ParentNode.Attributes[2].Value == "2")
                                {
                                    int id = 0;
                                    string[] names = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                                    for (int i = 0; i < names.Count(); i++)
                                    {
                                        if (names[i] == desc.name)
                                        {
                                            id = i;
                                            break;
                                        }
                                    }
                                    string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                                    max_val[id] = degree_box.Value.ToString();
                                    doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                                    for (int i = 0; i < max_val.Count(); i++)
                                    {
                                        doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val[i];
                                        if (i != max_val.Count() - 1)
                                            doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                                    }
                                    int[] values = new int[max_val.Count()];
                                    for (int i = 0; i < max_val.Count(); i++)
                                    {
                                        values[i] = Convert.ToInt32(max_val[i]);
                                    }
                                    values[id] = 0;
                                    List<List<int>> comb = new List<List<int>>();
                                    if (values.Count() > 1)
                                    {
                                        comb = Functions.combine(values);
                                    }
                                    else
                                    {
                                        comb.Add(new List<int>());
                                        comb[0].Add(values[id]);
                                    }
                                    foreach (List<int> l in comb)
                                    {
                                        l[id] = degree;
                                        foreach (int i in l)
                                        {
                                            node.InnerText += " " + i.ToString();
                                        }
                                        node.InnerText += ";";
                                    }
                                    doc.Save(link.path);
                                    break;
                                }
                            }

                        }
                    }
                }
                if (degree_box.IsDecremented())
                {
                    foreach (GenomePhenotypeLink link in genome_links)
                    {
                        doc = new MyXmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                        {
                            if (node.Attributes[1].Value == desc.name)
                            {
                                foreach (XmlNode n in node.ChildNodes[0].ChildNodes)
                                {
                                    if (Convert.ToInt32(n.Attributes[0].Value) > degree_box.Value)
                                    {
                                        n.ParentNode.RemoveChild(n);
                                    }
                                }
                            }
                            break;
                        }
                        doc.Save(link.path);
                    }
                    foreach (NaturalSelectionLink link in natsel_links)
                    {
                        doc = new MyXmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        int id = 0;
                        string[] names = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                        for (int i = 0; i < names.Count(); i++)
                        {
                            if (names[i] == desc.name)
                            {
                                id = i;
                                break;
                            }
                        }
                        string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                        max_val[id] = degree_box.Value.ToString();
                        doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                        for (int i = 0; i < max_val.Count(); i++)
                        {
                            doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val[i];
                            if (i != max_val.Count() - 1)
                                doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                        }
                        string[] inner1 = doc.GetElementsByTagName("characteristic_sets")[0].InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                        string[] inner2 = doc.GetElementsByTagName("characteristic_sets")[1].InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                        doc.GetElementsByTagName("characteristic_sets")[0].InnerText = null;
                        doc.GetElementsByTagName("characteristic_sets")[1].InnerText = null;
                        List<string> inner1_l = new List<string>();
                        List<string> inner2_l = new List<string>();
                        foreach (string s in inner1)
                        {
                            if (Convert.ToInt32(s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[id]) <= degree_box.Value)
                                inner1_l.Add(s);
                        }
                        foreach (string s in inner2)
                        {
                            if (Convert.ToInt32(s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[id]) <= degree_box.Value)
                                inner2_l.Add(s);
                        }
                        foreach (string s in inner1_l)
                        {
                            doc.GetElementsByTagName("characteristic_sets")[0].InnerText += " " + s + ";";
                        }
                        foreach (string s in inner2_l)
                        {
                            doc.GetElementsByTagName("characteristic_sets")[1].InnerText += " " + s + ";";
                        }
                        doc.Save(link.path);
                    }
                    foreach (ReproductionLink link in model.model_reproduction_links.Values)
                    {
                        if (link.path_to_phenotype_table == phen_t.path)
                        {
                            doc = new MyXmlDocument();
                            doc.LoadXml(System.IO.File.ReadAllText(link.path));
                            int id = 0;
                            string[] names = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Split(' ');
                            for (int i = 0; i < names.Count(); i++)
                            {
                                if (names[i] == desc.name)
                                {
                                    id = i;
                                    break;
                                }
                            }
                            string[] max_val = doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText.Split(' ');
                            max_val[id] = degree_box.Value.ToString();
                            doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText = null;
                            for (int i = 0; i < max_val.Count(); i++)
                            {
                                doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += max_val[i];
                                if (i != max_val.Count() - 1)
                                    doc.GetElementsByTagName("characteristic_value_diapasons")[0].InnerText += " ";
                            }
                            foreach (XmlNode node in doc.GetElementsByTagName("characteristic_sets"))
                            {
                                string[] inner = node.InnerText.Split(new char[] { '\t', '\n', '\r', ';' }, StringSplitOptions.RemoveEmptyEntries);
                                node.InnerText = null;
                                List<string> inner_l = new List<string>();
                                foreach (string s in inner)
                                {
                                    if (Convert.ToInt32(s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[id]) <= degree_box.Value)
                                        inner_l.Add(s);
                                }
                                foreach (string s in inner_l)
                                {
                                    node.InnerText += " " + s + ";";
                                }
                            }
                            doc.Save(link.path);
                        }
                    }
                }
                doc = new MyXmlDocument();
                doc.LoadXml(System.IO.File.ReadAllText(phen_t.path));
                foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                {
                    if (node.Attributes[1].Value == desc.name)
                    {
                        node.Attributes[2].Value = degree_box.Value.ToString();
                        break;
                    }
                }
                doc.Save(phen_t.path);
                int ind = charac_box.SelectedIndex;
                update();
                charac_box.SelectedIndex = ind;
            }
        }
        private void ok_butt_Click(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(phen_t.path));
            doc.DocumentElement.Attributes[0].Value = name_box.Text;
            doc.Save(phen_t.path);
            this.Close();
        }

        private void ren_butt_Click(object sender, EventArgs e)
        {
            if (charac_box.SelectedItem != null)
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(System.IO.File.ReadAllText(phen_t.path));
                foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                {
                    if (node.Attributes[1].Value == (string)charac_box.SelectedItem)
                    {
                    Rename:
                        RenameForm renf = new RenameForm();
                        if (renf.ShowDialog() == DialogResult.OK)
                        {
                            foreach (XmlNode n in doc.GetElementsByTagName("characteristic"))
                            {
                                if ((n.Attributes[1].Value == Data.new_name) && (node.Attributes[1].Value != Data.new_name))
                                {
                                    MessageBox.Show("A characteristic with this name already exists. Please, choose another name.");
                                    goto Rename;
                                }
                            }
                            node.Attributes[1].Value = Data.new_name;
                        }
                        break;
                    }
                }
                doc.Save(phen_t.path);
                foreach (ReproductionLink link in model.model_reproduction_links.Values)
                {
                    if (link.path_to_phenotype_table == phen_t.path)
                    {
                        doc = new XmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        doc.GetElementsByTagName("characteristic_names")[0].InnerText=doc.GetElementsByTagName("characteristic_names")[0].InnerText.Replace((string)charac_box.SelectedItem, Data.new_name);
                        doc.Save(link.path);
                    }
                }
                foreach (NaturalSelectionLink link in model.model_natural_selection_links.Values)
                {
                    if (link.path_to_phenotype_table == phen_t.path)
                    {
                        doc = new XmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        doc.GetElementsByTagName("characteristic_names")[0].InnerText = doc.GetElementsByTagName("characteristic_names")[0].InnerText.Replace((string)charac_box.SelectedItem, Data.new_name);
                        doc.Save(link.path);
                    }
                }
                foreach (GenomePhenotypeLink link in model.model_genome_phenotype_links.Values)
                {
                    if (link.path_to_phenotype_table == phen_t.path)
                    {
                        doc = new XmlDocument();
                        doc.LoadXml(System.IO.File.ReadAllText(link.path));
                        foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                        {
                            if (node.Attributes[1].Value == (string)charac_box.SelectedItem)
                            {
                                node.Attributes[1].Value = Data.new_name;
                                break;
                            }
                        }
                        doc.Save(link.path);
                    }
                }
                update();
            }
        }
    }
}
